package com.kuang.exam.modules.exam.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kuang.exam.core.api.dto.BaseIdsReqDTO;
import com.kuang.exam.core.api.dto.PagingReqDTO;
import com.kuang.exam.core.exception.ServiceException;
import com.kuang.exam.core.utils.BeanMapper;
import com.kuang.exam.core.utils.StringUtils;
import com.kuang.exam.modules.enums.JoinType;
import com.kuang.exam.modules.enums.OpenType;
import com.kuang.exam.modules.exam.dto.ExamDTO;
import com.kuang.exam.modules.exam.dto.ExamRepoDTO;
import com.kuang.exam.modules.exam.dto.request.ExamSaveReqDTO;
import com.kuang.exam.modules.exam.dto.response.ExamOnlineRespDTO;
import com.kuang.exam.modules.exam.dto.response.ExamReviewRespDTO;
import com.kuang.exam.modules.exam.entity.Exam;
import com.kuang.exam.modules.exam.entity.ExamLesson;
import com.kuang.exam.modules.exam.mapper.ExamMapper;
import com.kuang.exam.modules.exam.service.ExamDepartService;
import com.kuang.exam.modules.exam.service.ExamLessonService;
import com.kuang.exam.modules.exam.service.ExamRepoService;
import com.kuang.exam.modules.exam.service.ExamService;
import com.kuang.exam.modules.paper.entity.Paper;
import com.kuang.exam.modules.paper.enums.ExamState;
import com.kuang.exam.modules.paper.service.PaperQuAnswerService;
import com.kuang.exam.modules.paper.service.PaperQuService;
import com.kuang.exam.modules.paper.service.PaperService;
import com.kuang.exam.modules.sys.depart.entity.SysDepart;
import com.kuang.exam.modules.sys.depart.service.SysDepartService;
import com.kuang.exam.modules.sys.lesson.dto.UserLessonDTO;
import com.kuang.exam.modules.sys.lesson.service.SysUserLessonService;
import com.kuang.exam.modules.sys.user.entity.SysUser;
import com.kuang.exam.modules.sys.user.service.SysUserService;
import com.kuang.exam.modules.user.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 考试业务实现类
 * </p>
 */
@Service
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService {


    @Autowired
    private ExamRepoService examRepoService;

    @Autowired
    private ExamDepartService examDepartService;

    @Autowired
    private ExamLessonService examLessonService;

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysUserLessonService userLessonService;

    @Autowired
    private PaperService paperService;

    @Autowired
    private PaperQuService paperQuService;

    @Autowired
    private PaperQuAnswerService paperQuAnswerService;

    @Override
    public void save(ExamSaveReqDTO reqDTO) {

        // ID 为空是添加，不为空是修改
        String id = reqDTO.getId();
        if (StringUtils.isBlank(id)) {
            id = IdWorker.getIdStr();
        }

        //复制参数
        Exam entity = new Exam();

        // 复制基本数据
        BeanMapper.copy(reqDTO, entity);
        entity.setId(id);

        String userId = UserUtils.getUserId();
        entity.setTeacherId(userId);

        // 修复状态
        if (reqDTO.getTimeLimit() != null
                && !reqDTO.getTimeLimit()
                && reqDTO.getState() != null
                && reqDTO.getState() == 2) {
            entity.setState(0);
        } else {
            entity.setState(reqDTO.getState());
        }

        // 题库组卷
        if (JoinType.REPO_JOIN.equals(reqDTO.getJoinType())) {
            try {
                examRepoService.saveAll(id, reqDTO.getRepoList());
            } catch (DuplicateKeyException e) {
                throw new ServiceException(1, "不能选择重复的题库！");
            }
        }

        // 指定班级开放
        if (OpenType.DEPT_OPEN.equals(reqDTO.getOpenType())) {
            examDepartService.saveAll(id, reqDTO.getDepartIds());
        }

        // 指定课程开放
        if (OpenType.LESSON_OPEN.equals(reqDTO.getOpenType())) {
            ExamLesson examLesson = new ExamLesson();
            examLesson.setExamId(id);
            examLesson.setLessonId(reqDTO.getLessonId());
            examLessonService.save(examLesson);
        }

        this.saveOrUpdate(entity);

    }

    @Override
    public void remove(BaseIdsReqDTO reqDTO) {
        //根据ID删除exam
        this.removeByIds(reqDTO.getIds());

        // 1、同步删除exam_repo、exam_lesson、exam_dept
        // 2、删除所有考生的这场考试信息paper
        if (reqDTO.getIds() != null && reqDTO.getIds().size() != 0) {
            Map<String, Object> columnMap = new HashMap<>();
            reqDTO.getIds().forEach(examId -> {
                columnMap.put("exam_id", examId);
                examLessonService.removeByMap(columnMap);
                examDepartService.removeByMap(columnMap);
                examRepoService.removeByMap(columnMap);

                // 删除试卷
                List<Paper> papers = paperService.listByExamId(examId);
                Map<String, Object> columnPaperMap = new HashMap<>();
                papers.forEach(paper -> {
                    columnPaperMap.put("paper_id", paper.getId());
                    paperService.removeById(paper.getId());
                    paperQuService.removeByMap(columnPaperMap);
                    paperQuAnswerService.removeByMap(columnPaperMap);
                });
            });
        }
    }

    @Override
    public ExamSaveReqDTO findDetail(String id) {
        ExamSaveReqDTO respDTO = new ExamSaveReqDTO();
        Exam exam = this.getById(id);
        BeanMapper.copy(exam, respDTO);

        // 考试部门
        List<String> departIds = examDepartService.listByExam(id);
        respDTO.setDepartIds(departIds);

        // 题库
        List<ExamRepoDTO> repos = examRepoService.listByExam(id);
        respDTO.setRepoList(repos);

        // 考试课程
        ExamLesson examLesson = examLessonService.getByExamId(id);
        respDTO.setLessonId(examLesson != null ? examLesson.getLessonId() : "");

        return respDTO;
    }

    @Override
    public ExamDTO findById(String id) {
        ExamDTO respDTO = new ExamDTO();
        Exam exam = this.getById(id);
        BeanMapper.copy(exam, respDTO);
        return respDTO;
    }

    @Override
    public IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO) {

        //创建分页对象
        Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize());

        // 未指定或完全开放
        if (reqDTO.getParams() != null && (reqDTO.getParams().getOpenType() == null || reqDTO.getParams().getOpenType() == 1)) {
            // 将班级和课程置空
            reqDTO.getParams().setDeptName(null);
            reqDTO.getParams().setLessonName(null);
        }

        //转换结果
        IPage<ExamDTO> pageData = baseMapper.paging(page, reqDTO.getParams());

        // 处理班级
        if (reqDTO.getParams() != null && reqDTO.getParams().getOpenType() != null && reqDTO.getParams().getOpenType() == 2) {

            HashMap<String, ExamDTO> resultMap= new HashMap<>();
            for (ExamDTO examDTO : pageData.getRecords()) {
                if (resultMap.containsKey(examDTO.getId())){
                    ExamDTO currentExam = resultMap.get(examDTO.getId());
                    resultMap.get(examDTO.getId()).setDeptName(currentExam.getDeptName()+", "+examDTO.getDeptName());
                }else {
                    resultMap.put(examDTO.getId(), examDTO);
                }

            }
            List<ExamDTO> result = new ArrayList<>(resultMap.values());
            pageData.setRecords(result);
        }

        return pageData;
    }

    @Override
    public IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO) {


        // 创建分页对象
        Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize());

        String userId = UserUtils.getUserId();
        SysUser user = userService.getById(userId);
        // 学生的课程
        List<UserLessonDTO> userLessonDTOS = userLessonService.listByUserId();
        List<String> lessonIds = new ArrayList<>(userLessonDTOS.size());
        userLessonDTOS.forEach(userLessonDTO -> lessonIds.add(userLessonDTO.getLessonId()));

        // 查找分页、参数：分页对象、学生的班级、课程、前端筛选条件
        IPage<ExamOnlineRespDTO> pageData = baseMapper.online(page, user.getDepartId(), lessonIds, reqDTO.getParams());
        // 修改考试状态
        pageData.getRecords().forEach(examOnlineRespDTO -> {
            // 考试状态为考试中，且当前考生已参加了该场考试，修改考试状态
            if (examOnlineRespDTO.getState().equals(ExamState.ENABLE)
                    && paperService.isExist(userId, examOnlineRespDTO.getId())) {
                examOnlineRespDTO.setState(ExamState.FINISHED);
            }

        });
        return pageData;
    }

    @Override
    public IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO) {
        // 创建分页对象
        Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize());

        // 查找分页
        IPage<ExamReviewRespDTO> pageData = baseMapper.reviewPaging(page, reqDTO.getParams());

        return pageData;
    }


    /**
     * 计算分值
     *
     * @param reqDTO
     */
    private void calcScore(ExamSaveReqDTO reqDTO) {

        // 主观题分数
        int objScore = 0;

        // 题库组卷
        if (JoinType.REPO_JOIN.equals(reqDTO.getJoinType())) {
            List<ExamRepoDTO> repoList = reqDTO.getRepoList();

            for (ExamRepoDTO item : repoList) {
                if (item.getRadioCount() != null && item.getRadioCount() > 0
                        && item.getRadioScore() != null && item.getRadioScore() > 0) {
                    objScore += item.getRadioCount() * item.getRadioScore();
                }
                if (item.getMultiCount() != null && item.getMultiCount() > 0
                        && item.getMultiScore() != null && item.getMultiScore() > 0) {
                    objScore += item.getMultiCount() * item.getMultiScore();
                }
                if (item.getJudgeCount() != null && item.getJudgeCount() > 0
                        && item.getJudgeScore() != null && item.getJudgeScore() > 0) {
                    objScore += item.getJudgeCount() * item.getJudgeScore();
                }
                if (item.getFillCount() != null && item.getFillCount() > 0
                        && item.getFillScore() != null && item.getFillScore() > 0) {
                    objScore += item.getFillCount() * item.getFillScore();
                }
                if (item.getSubjectCount() != null && item.getSubjectCount() > 0
                        && item.getSubjectScore() != null && item.getSubjectScore() > 0) {
                    objScore += item.getSubjectCount() * item.getSubjectScore();
                }
            }
        }


        reqDTO.setTotalScore(objScore);
    }

}
